/*-------------------------------------------------------------------------------
 -- Title      : x264 acceleration   
 -- Project    : 
-------------------------------------------------------------------------------
 -- File       : x264_rovex.c
 -- Author     : Alex Luna 
		 Javier James
 -- School     : Technical University Delft 
 -- Created    : Wed 24 Oct. 2013
 -- Last update: Wed 31 Oct. 2013
 -- Platform   : FPGA ml640 , rovex and microblaze
 -- Standard   : C90
 -------------------------------------------------------------------------------
 -- Description: The application ports a kernel from the x264 application on the rovex.  
 -- 		 Application takes two pixel images, and applies the Hadamard algorithm on it.  

        Data mapping for dmem: 
	pixel1:  0x120 - 0x13F    32 bytes
	pixel2:  0x140 - 0x15F    32 bytes 
	result:  0x120 - 0x124    4 bytes

-------------------------------------------------------------------------------
 -- Revisions Last update:
 -- Date        Version  Author        Description
 -- 2013-10-24  1.0      Javier        Created
 -- 2013-10-26  1.1	 Alex	       Modified
 -- 2013-10-31  1.2	 Alex	       Modified
-------------------------------------------------------------------------------
*/

#include <stdlib.h>
#include <stdio.h>

#define DATA_SIZE 16 


//typedef char uint8_t;
typedef unsigned char uint8_t;
typedef unsigned short int  uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
typedef long intptr_t; 
typedef uint8_t  pixel;
typedef uint16_t sum_t;
typedef uint32_t sum2_t;







#define SYSTEM_BITS  64
#define HIGH_BIT_DEPTH 0
#define X264_BIT_DEPTH     8
#define BIT_DEPTH X264_BIT_DEPTH
#define BITS_PER_SUM (8 * sizeof(sum_t))
#define HADAMARD4(d0, d1, d2, d3, s0, s1, s2, s3) {\
    sum2_t t0 = s0 + s1;\
    sum2_t t1 = s0 - s1;\
    sum2_t t2 = s2 + s3;\
    sum2_t t3 = s2 - s3;\
    d0 = t0 + t2;\
    d2 = t0 - t2;\
    d1 = t1 + t3;\
    d3 = t1 - t3;\
}

/* global variables declaration */
extern char __DATA_START;

/* function declarations */


static  sum2_t abs2( sum2_t a ) 
{
    sum2_t s =  ((a>>(BITS_PER_SUM-1))&(((sum2_t)1<<BITS_PER_SUM)+1))*((sum_t)-1);
    return (a+s)^s;
}

static int x264_pixel_satd_4x4( pixel *pix1, intptr_t i_pix1, pixel *pix2, intptr_t i_pix2 );


//static int x264_pixel_satd_8x4( pixel *pix1, intptr_t i_pix1, pixel *pix2, intptr_t i_pix2 );

intptr_t index_px1 = 4;	
intptr_t index_px2 = 4;	


/*main function*/
int main(int argc, char **argv) 
{
    pixel *pixel1=NULL;		
    pixel *pixel2=NULL;		

    int *kernel_result=NULL;		
    int i;			

    pixel1 = (char *) &__DATA_START ;            // 0X120
    pixel2 = (char *) &__DATA_START + DATA_SIZE; // 0X140
    kernel_result = (int *) 0x120;


//-------------------------------------------------------------------------------
//    Calculate return value and send to Dmem
//-------------------------------------------------------------------------------

    /* Store result at location pointed by kernel_result */
    // *kernel_result = x264_pixel_satd_8x4( pixel1, index_px1, pixel2, index_px2 );

 *kernel_result= x264_pixel_satd_4x4( pixel1 ,index_px1 ,pixel2 , index_px2  );
 //*kernel_result=30;// x264_pixel_satd_4x4( pixel1 ,index_px1 ,pixel2 , index_px2  );

    return 0;
}//end main function



/* actual kernel */
static int x264_pixel_satd_4x4( pixel *pix1, intptr_t i_pix1, pixel *pix2, intptr_t i_pix2 )
//static int x264_pixel_satd_8x4( pixel *pix1, intptr_t i_pix1, pixel *pix2, intptr_t i_pix2 )
{
    sum2_t tmp[4][2];
    sum2_t a0, a1, a2, a3, b0,b1;
    sum2_t sum = 0;
    sum2_t temp ;
    int i;


        a0 = pix1[0 ] - pix2[0];
        a1 = pix1[1 ] - pix2[1 ];
        b0 = (a0+a1) + ((a0-a1)<<BITS_PER_SUM);
   temp = pix1[1];  
   for( i = 0; i < 4; i++ )
    {
        a0 = pix1[0+4*i ] - pix2[0+4*i];
        a1 = pix1[1+4*i ] - pix2[1+4*i ];
        b0 = (a0+a1) + ((a0-a1)<<BITS_PER_SUM);
        a2 = pix1[2+4*i ] - pix2[2 +4*i];
        a3 = pix1[3+4*i ] - pix2[3+4*i ];
        b1 = (a2+a3) + ((a2-a3)<<BITS_PER_SUM);
        tmp[i][0] = b0 + b1;
        tmp[i][1] = b0 - b1;
    }

//   temp = tmp[0][0]; 
   for( i = 0; i < 2; i++ )
    {
        HADAMARD4( a0, a1, a2, a3, tmp[0][i], tmp[1][i], tmp[2][i], tmp[3][i] );
        a0 = abs2(a0) + abs2(a1) + abs2(a2) + abs2(a3);
        sum += ((sum_t)a0) + (a0>>BITS_PER_SUM);

//	if(i==0)
//	temp= sum; 

    }
     return sum >> 1;
//	return temp; 



}


